<template>
  <div class="trust-evaluation-container">
    <div class="main-layout">
      <!-- 左侧侧边栏 -->
      <div class="sidebar-controls">
        <div class="sidebar-header">
          <h1 class="sidebar-title">可信评估系统</h1>
            </div>
        
        <!-- 可信度图例 -->
        <div class="control-section">
          <div class="section-title">可信度标识</div>
          <div class="trust-legend">
            <div class="legend-item">
              <div class="color-bar" style="background-color: #FF0000;"></div>
              <span>0-9</span>
                      </div>
            <div class="legend-item">
              <div class="color-bar" style="background-color: #FF3300;"></div>
              <span>10-19</span>
                      </div>
            <div class="legend-item">
              <div class="color-bar" style="background-color: #FF6600;"></div>
              <span>20-29</span>
              </div>
            <div class="legend-item">
              <div class="color-bar" style="background-color: #FF9900;"></div>
              <span>30-39</span>
            </div>
            <div class="legend-item">
              <div class="color-bar" style="background-color: #FFCC00;"></div>
              <span>40-49</span>
            </div>
            <div class="legend-item">
              <div class="color-bar" style="background-color: #FFFF00;"></div>
              <span>50-59</span>
                  </div>
            <div class="legend-item">
              <div class="color-bar" style="background-color: #CCFF00;"></div>
              <span>60-64</span>
            </div>
            <div class="legend-item">
              <div class="color-bar" style="background-color: #99FF00;"></div>
              <span>65-69</span>
                  </div>
            <div class="legend-item">
              <div class="color-bar" style="background-color: #66FF00;"></div>
              <span>70-74</span>
                </div>
            <div class="legend-item">
              <div class="color-bar" style="background-color: #33FF00;"></div>
              <span>75-79</span>
              </div>
            <div class="legend-item">
              <div class="color-bar" style="background-color: #00FF00;"></div>
              <span>80-84</span>
          </div>
            <div class="legend-item">
              <div class="color-bar" style="background-color: #00CC00;"></div>
              <span>85-89</span>
            </div>
            <div class="legend-item">
              <div class="color-bar" style="background-color: #009900;"></div>
              <span>90-94</span>
            </div>
            <div class="legend-item">
              <div class="color-bar" style="background-color: #006600;"></div>
              <span>95-100</span>
            </div>
          </div>
        </div>
        
        <!-- 文字搜索部分 -->
        
        <!-- 实体类型选择 -->
        <div class="control-section">
          <div class="section-title">实体类型</div>
          <div class="entity-types">
            <el-checkbox v-for="type in entityTypes" 
                         :key="type.type" 
                         v-model="entityTypeFilters[type.type]" 
                         :label="type.type" />
            <div v-if="entityTypes.length === 0" class="no-types-message">
              暂无实体类型数据
            </div>
          </div>
        </div>
        <!-- 筛选按钮 -->
        <div class="control-section">
          <el-button type="primary" 
                     class="filter-button" 
                     @click="applyFilters" 
                     :loading="loading">
            应用筛选
                </el-button>
          <el-button type="info" 
                     class="filter-button" 
                     @click="resetFilters" 
                     :disabled="loading">
            重置筛选
                </el-button>
              </div>
            </div>
            
      <!-- 右侧主内容区域 -->
      <div class="main-content">
        <!-- 图谱区域 -->
        <div class="graph-area">
          <div v-if="loading" class="loading-overlay">
            <div class="spinner"></div>
            <div>加载中...</div>
          </div>
          
          <div v-else-if="error" class="error-container">
            <el-empty 
              description="加载图谱数据失败" 
              :image-size="100"
            >
              <el-button @click="loadGraphData">重试</el-button>
            </el-empty>
          </div>
          
          <div v-else class="graph-container" ref="graphContainer">
            <div v-if="graphData.nodes.length > 0 && !graphRendered" class="graph-loading">
              <div class="spinner"></div>
              <div>渲染中...</div>
              </div>
          </div>
          
          <!-- 节点信息面板 -->
          <div v-if="selectedNode" class="node-info-panel">
            <div class="node-info-header">
              <h3>节点信息</h3>
                <el-button 
                type="text" 
                @click="closeNodeInfo"
                icon="el-icon-close"
              ></el-button>
              </div>
            <div class="node-info-content">
              <div class="info-item">
                <div class="item-label">ID</div>
                <div class="item-value">{{ selectedNode.id }}</div>
              </div>
              <div class="info-item">
                <div class="item-label">名称</div>
                <div class="item-value">{{ selectedNode.name || selectedNode.id }}</div>
              </div>
              <div class="info-item">
                <div class="item-label">类型</div>
                <div class="item-value">
                  <el-tag 
                    :type="getTypeColor(selectedNode.type)" 
                  size="small" 
                  >
                    {{ selectedNode.type }}
                  </el-tag>
              </div>
            </div>
              <div 
                v-for="(value, key) in selectedNodeProperties" 
                :key="key"
                class="info-item"
              >
                <div class="item-label">{{ key }}</div>
                <div class="item-value">{{ value }}</div>
          </div>
            </div>
          </div>
        </div>
        
        <!-- 评估结果区域 - 条件渲染 -->
        <div v-if="evaluationResult" class="evaluation-results">
          <div class="result-header">
            <h3>评估结果</h3>
            <div class="trust-score-badge" :class="getTrustScoreClass">
              {{ (evaluationResult.trust_score * 100).toFixed(0) }}% 可信度
            </div>
          </div>
          
          <div class="result-content">
            <div class="explanation">
              {{ evaluationResult.explanation || "可信度评估完成" }}
          </div>
          
            <div class="factors-section">
              <h4>评分细节</h4>
              <div class="factors-grid">
                <div class="factor-card" v-for="(score, factor) in evaluationResult.factors" :key="factor">
                  <div class="factor-title">{{ getFactorName(factor) }}</div>
                  <el-progress 
                    type="dashboard" 
                    :percentage="getPercentage(score)" 
                    :color="getScoreColor(score)"
                  />
                  <div class="factor-score">{{ score.toFixed(2) }}</div>
              </div>
              </div>
              </div>
              </div>
            </div>
          </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted, onBeforeUnmount, nextTick, watch } from 'vue'
import { ElMessage } from 'element-plus'
import axios from 'axios'
import * as d3 from 'd3'
import { 
  QuestionFilled as ElIconQuestionFilled,
  Check as ElIconCheck, 
  Tickets as ElIconTickets,
  Refresh as ElIconRefresh,
  RefreshRight as ElIconRefreshRight,
  Search as ElIconSearch,
  Close as ElIconClose  
} from '@element-plus/icons-vue'

// 状态定义
const loading = ref(false)
const error = ref(null)
const evaluating = ref(false)
const evaluatingAll = ref(false)
const graphData = ref({ nodes: [], links: [] })
const graphContainer = ref(null)
const showHighTrustOnly = ref(false)
const searchQuery = ref('')
const simulation = ref(null)
const selectedNode = ref(null)
const graphRendered = ref(false)
const nodeLimit = ref(150)
const entityTypes = ref([])

// 评估表单
const evaluationForm = reactive({
  sourceId: '',
  targetId: '',
  relationType: ''
})

// 实体类型过滤器
const entityTypeFilters = reactive({})

// 图谱相关变量
let svg = null
let g = null
let zoom = null
let width = 0
let height = 0

// 相关数据
const evaluationResult = ref(null)
const entityOptions = ref([])
const targetEntityOptions = ref([])
const availableRelations = ref([])

// 颜色映射
const trustScoreColors = {
  '0-9': '#FF0000',
  '10-19': '#FF3300',
  '20-29': '#FF6600',
  '30-39': '#FF9900',
  '40-49': '#FFCC00',
  '50-59': '#FFFF00',
  '60-64': '#CCFF00',
  '65-69': '#99FF00',
  '70-74': '#66FF00',
  '75-79': '#33FF00',
  '80-84': '#00FF00',
  '85-89': '#00CC00',
  '90-94': '#009900',
  '95-100': '#006600'
}

// 节点颜色
const nodeColors = {
  'Malware': '#F56C6C',
  'Vulnerability': '#E6A23C',
  'Tool': '#67C23A',
  'Organization': '#409EFF',
  'Person': '#9C27B0',
  'System': '#2196F3',
  'URL': '#FF9800',
  'File': '#607D8B',
  'Entity': '#4CAF50',  // 绿色，对应图片中的绿色节点
  // 保留原有类型映射
  'Ip': '#F56C6C',
  'Domain': '#E6A23C',
  'Url': '#E6A23C',
  'Email': '#67C23A',
  'Cve': '#F56C6C',
  'Threat_actor': '#F44336', // 红色，对应图片中的红色节点
  'Hash': '#909399',
  'Context': '#409EFF',
  // 新增类型映射，更接近图片中的颜色
  'Location': '#3F51B5',  // 靛蓝色
  'Concept': '#9C27B0',   // 紫色
  'Event': '#E91E63',     // 粉色
  'Activity': '#00BCD4',  // 青色
  '人物': '#9C27B0',       // 紫色，对应图片中的紫色节点
  '事件': '#E91E63',       // 粉色，对应图片中的事件节点
  'Unknown': '#9E9E9E'    // 灰色
}

// 计算属性
const isFormValid = computed(() => {
  return evaluationForm.sourceId && evaluationForm.targetId && evaluationForm.relationType
})

const getTrustScoreClass = computed(() => {
  if (!evaluationResult.value) return ''
  
  const score = evaluationResult.value.trust_score
  if (score > 0.8) return 'high-trust'
  if (score > 0.6) return 'medium-trust'
  return 'low-trust'
})

// 节点类型列表
const nodeTypes = computed(() => {
  const types = new Set()
  graphData.value.nodes.forEach(node => {
    if (node.type) {
      types.add(node.type)
    }
  })
  return Array.from(types)
})

// 计算选中节点的属性
const selectedNodeProperties = computed(() => {
  if (!selectedNode.value) return {}
  
  const excludeFields = ['id', 'name', 'type', 'index', 'x', 'y', 'vx', 'vy', 'fx', 'fy']
  const properties = {}
  
  Object.entries(selectedNode.value).forEach(([key, value]) => {
    if (!excludeFields.includes(key) && value !== undefined && value !== null) {
      properties[key] = value
    }
  })
  
  return properties
})

// 生命周期钩子
onMounted(() => {
  loadGraphData()
  loadEntityOptions()
  loadEntityTypes()
  
  // 添加窗口大小变化监听
  const resizeObserver = new ResizeObserver(() => {
    if (graphContainer.value && graphData.value.nodes.length > 0) {
      nextTick(() => {
        forceRenderGraph()
      })
    }
  })
  
  if (graphContainer.value) {
    resizeObserver.observe(graphContainer.value)
  }
  
  // 延迟渲染
  setTimeout(() => {
    if (graphContainer.value && graphData.value.nodes.length > 0) {
      console.log('Forcing graph reinitialization after timeout')
      forceRenderGraph()
    }
  }, 1000)
  
  // 组件销毁前清理
  onBeforeUnmount(() => {
    if (simulation.value) {
      simulation.value.stop()
    }
    
    resizeObserver.disconnect()
  })
})

// 方法定义
const loadGraphData = async () => {
  loading.value = true
  error.value = null
  graphRendered.value = false
  
  try {
    console.log('从后端加载图谱数据')
    
    // 选择与KnowledgeGraph.vue相同的endpoint
    const selectedEndpoint = 'test-graph'
    const url = `http://localhost:8000/${selectedEndpoint}`
    console.log('Fetching graph data from:', url)
    
    // 获取认证令牌
    const token = localStorage.getItem('token')
    
    // 设置请求头，包含认证信息
    const headers = {}
    if (token) {
      headers['Authorization'] = `Bearer ${token}`
    }
    
    // 从后端API获取数据
    const response = await axios.get(url, { headers })
    
    if (response.data && response.data.nodes && response.data.links) {
      // 处理从API接收到的数据，与KnowledgeGraph.vue保持一致
      graphData.value = {
        nodes: response.data.nodes.map(node => ({
          ...node,
          // 确保节点有id和type属性
          id: node.id || `node-${Math.random().toString(36).substring(2, 9)}`,
          type: node.type || 'Unknown',
          name: node.name || node.label || node.id,
          // 如果没有可信度评分，使用随机值（实际场景应从API获取）
          trust_score: node.trust_score !== undefined ? node.trust_score : Math.random()
        })),
        links: response.data.links.map(link => ({
          ...link,
          // 确保链接有source、target和type属性
          id: link.id || `link-${Math.random().toString(36).substring(2, 9)}`,
          source: link.source,
          target: link.target,
          type: link.type || '关联',
          // 如果没有可信度评分，使用随机值（实际场景应从API获取）
          trust_score: link.trust_score !== undefined ? link.trust_score : Math.random()
        }))
      }
      
      console.log(`成功加载 ${graphData.value.nodes.length} 个节点和 ${graphData.value.links.length} 个关系`)
      
      // 确保DOM更新完成后初始化图谱
      await nextTick();
      
      // 添加一个短延迟，确保DOM完全渲染
      setTimeout(() => {
        console.log('延迟后检查图谱容器', graphContainer.value);
        if (graphContainer.value) {
          console.log('容器存在，初始化图谱');
          initGraph();
          forceRenderGraph();
        } else {
          console.error('Graph container element not found');
          error.value = '图谱容器元素未找到';
        }
      }, 500);
      
      // 设置实体选项
      entityOptions.value = graphData.value.nodes;
      
    } else {
      throw new Error('API返回数据格式不正确');
    }
  } catch (err) {
    console.error('加载图谱数据失败:', err);
    error.value = err.message || '加载失败';
    ElMessage.error('加载图谱数据失败');
  } finally {
    loading.value = false;
  }
}

const loadEntityOptions = async () => {
  try {
    // 获取认证令牌
    const token = localStorage.getItem('token')
    
    // 设置请求头，包含认证信息
    const headers = {}
    if (token) {
      headers['Authorization'] = `Bearer ${token}`
    }
    
    // 尝试从实体API获取数据
    // const response = await axios.get('http://localhost:8000/entities', { headers })
    
    // // 过滤掉Context类型的节点
    // if (response.data && Array.isArray(response.data)) {
    //   const filteredNodes = response.data.filter(node => node.type !== 'Context')
    // entityOptions.value = filteredNodes
    //   console.log(`成功加载 ${entityOptions.value.length} 个实体选项`)
    // } else {
    //   // 如果实体API没有返回有效数据，使用图谱数据
    //   entityOptions.value = graphData.value.nodes
    //   console.log('使用图谱数据作为实体选项')
    // }
  } catch (err) {
    console.error('加载实体选项失败:', err)
    ElMessage.error('加载实体选项失败')
    // 使用图谱数据作为备选
    entityOptions.value = graphData.value.nodes
  }
}

const handleSourceChange = () => {
  evaluationForm.targetId = ''
  evaluationForm.relationType = ''
  
  // 根据选择的源实体，找出可能的关系和目标实体
  const sourceId = evaluationForm.sourceId
  if (!sourceId) {
    targetEntityOptions.value = []
    availableRelations.value = []
    return
  }
  
  // 找出与源实体相关的所有链接
  const relevantLinks = graphData.value.links.filter(link => link.source === sourceId)
  
  // 收集目标实体和关系类型
  const targets = new Set()
  const relations = new Set()
  
  relevantLinks.forEach(link => {
    targets.add(link.target)
    relations.add(link.type)
  })
  
  // 设置可用的关系类型
  availableRelations.value = Array.from(relations)
  
  // 设置可用的目标实体
  targetEntityOptions.value = entityOptions.value.filter(entity => targets.has(entity.id))
}

const evaluateTrust = async () => {
  if (!isFormValid.value) return
  
  evaluating.value = true
  
  try {
    // 模拟API调用，生成随机评估结果
    const mockResult = {
      trust_score: Math.random(),
      explanation: "基于多个因素的综合评估，此三元组的可信度分析已完成。根据来源可靠性、数据一致性和时效性等指标进行评估。",
      factors: {
        provenance_score: Math.random(),
        consistency_score: Math.random(),
        timeliness_score: Math.random(),
        semantic_score: Math.random(),
        path_score: Math.random()
      }
    }
    
    // 直接使用模拟数据
    evaluationResult.value = mockResult
    ElMessage.success('可信度评估完成')
    
    // 更新链接的可信度分数
    const linkKey = `${evaluationForm.sourceId}-${evaluationForm.relationType}-${evaluationForm.targetId}`
    const linkIndex = graphData.value.links.findIndex(l => 
      l.source === evaluationForm.sourceId && 
      l.target === evaluationForm.targetId && 
      l.type === evaluationForm.relationType
    )
    
    if (linkIndex >= 0) {
      graphData.value.links[linkIndex].trust_score = mockResult.trust_score
      // 刷新图数据
      forceRenderGraph()
    }
    
  } catch (err) {
    console.error('可信度评估失败:', err)
    ElMessage.error('可信度评估失败: ' + (err.response?.data?.detail || err.message))
  } finally {
    evaluating.value = false
  }
}

const evaluateAllTriples = async () => {
  evaluatingAll.value = true
  
  try {
    // 模拟批量评估，为所有链接分配随机可信度
    graphData.value.links.forEach(link => {
      link.trust_score = Math.random()
    })
    
    ElMessage.success(`已评估 ${graphData.value.links.length} 个三元组的可信度`)
    
    // 刷新图数据
    forceRenderGraph()
    
  } catch (err) {
    console.error('评估所有三元组失败:', err)
    ElMessage.error('评估所有三元组失败: ' + (err.message))
  } finally {
    evaluatingAll.value = false
  }
}

const getTypeColor = (type) => {
  const colorMap = {
    'Malware': 'danger',
    'Vulnerability': 'warning',
    'Tool': 'success',
    'Organization': 'primary',
    'Person': 'info',
    'System': 'primary',
    'URL': 'warning',
    'File': 'info',
    'Entity': 'info',
    // 保留原有类型映射
    'Ip': 'danger',
    'Domain': 'warning',
    'Url': 'warning',
    'Email': 'success',
    'Cve': 'danger',
    'Threat_actor': 'danger',
    'Hash': 'info',
    'Context': 'primary',
    // 新增类型映射
    'Location': 'primary',
    'Concept': 'info',
    'Event': 'danger',
    'Activity': 'success',
    'Unknown': 'info'
  }
  return colorMap[type] || 'info'
}

const getFactorName = (factor) => {
  const factorMap = {
    'provenance_score': '来源可信度',
    'consistency_score': '一致性',
    'timeliness_score': '时效性',
    'semantic_score': '语义兼容性',
    'path_score': '路径支持度'
  }
  return factorMap[factor] || factor
}

const getPercentage = (score) => {
  return Math.round(score * 100)
}

const getScoreColor = (score) => {
  if (score > 0.8) return '#67C23A'  // 绿色 - 高可信
  if (score > 0.6) return '#E6A23C'  // 橙色 - 中可信
  return '#F56C6C'                   // 红色 - 低可信
}

// 获取节点颜色
const getNodeColor = (type) => {
  return nodeColors[type] || '#909399'
}

// 获取可信度颜色
const getTrustScoreColor = (score) => {
  const scorePercent = Math.floor(score * 100)
  
  if (scorePercent < 10) return trustScoreColors['0-9']
  if (scorePercent < 20) return trustScoreColors['10-19']
  if (scorePercent < 30) return trustScoreColors['20-29']
  if (scorePercent < 40) return trustScoreColors['30-39']
  if (scorePercent < 50) return trustScoreColors['40-49']
  if (scorePercent < 60) return trustScoreColors['50-59']
  if (scorePercent < 65) return trustScoreColors['60-64']
  if (scorePercent < 70) return trustScoreColors['65-69']
  if (scorePercent < 75) return trustScoreColors['70-74']
  if (scorePercent < 80) return trustScoreColors['75-79']
  if (scorePercent < 85) return trustScoreColors['80-84']
  if (scorePercent < 90) return trustScoreColors['85-89']
  if (scorePercent < 95) return trustScoreColors['90-94']
  return trustScoreColors['95-100']
}

// 获取关系类型颜色
const relationColors = {
  '关联': '#999999',
  '属于': '#2196F3',
  '包含': '#9C27B0',
  '作用于': '#4CAF50',
  '起源于': '#FF5722',
  '引起': '#F44336',
  '导致': '#E91E63',
  '监测': '#3F51B5',
  '预防': '#4CAF50',
  '提供': '#8BC34A',
  '研发': '#00BCD4',
  '控制': '#673AB7',
  '产生': '#FFC107',
  '确定': '#607D8B',
  '协调': '#009688',
  '指导': '#03A9F4',
  '需要': '#FF9800'
}

const getRelationColor = (type) => {
  return relationColors[type] || '#999999'
}

// 初始化图谱
const initGraph = () => {
  if (!graphContainer.value) {
    console.error('Graph container element not found')
    return
  }
  
  console.log('Initializing graph visualization')
  
  // 清除现有内容
  d3.select(graphContainer.value).selectAll('*').remove()
  
  // 获取容器尺寸
  const container = graphContainer.value
  width = container.clientWidth || 800
  height = container.clientHeight || 600
  
  // 确保容器有明确的尺寸
  container.style.height = '600px'
  
  console.log('Container dimensions:', width, height)
  
  // 创建SVG元素
  svg = d3.select(container)
    .append('svg')
    .attr('width', width)
    .attr('height', height)
    .attr('viewBox', `0 0 ${width} ${height}`)
    .attr('class', 'graph-svg')
    .style('background-color', '#21252b')  // 深色背景
  
  // 定义箭头
  const defs = svg.append('defs')
  
  // 默认箭头
  defs.append('marker')
    .attr('id', 'arrowhead')
    .attr('viewBox', '-0 -5 10 10')
    .attr('refX', 25)
    .attr('refY', 0)
    .attr('orient', 'auto')
    .attr('markerWidth', 8)
    .attr('markerHeight', 8)
    .attr('xoverflow', 'visible')
    .append('svg:path')
    .attr('d', 'M 0,-5 L 10 ,0 L 0,5')
    .attr('fill', '#999')
    .style('stroke', 'none')
  
  // 创建主容器
  g = svg.append('g')
  
  // 实现缩放功能
  zoom = d3.zoom()
    .scaleExtent([0.1, 10])
    .on('zoom', (event) => {
      g.attr('transform', event.transform)
    })
  
  svg.call(zoom)
  
  // 初始化力导向图布局
  simulation.value = d3.forceSimulation()
    .force('link', d3.forceLink().id(d => d.id).distance(150))
    .force('charge', d3.forceManyBody().strength(-300))
    .force('center', d3.forceCenter(width / 2, height / 2))
    .force('collide', d3.forceCollide().radius(50))
    
  // 更新图谱
  updateGraph()
  
  // 标记为已渲染
  graphRendered.value = true
}

// 更新图谱
const updateGraph = () => {
  console.log('Updating graph visualization')
  if (!g || !simulation.value) {
    console.error('Missing graph elements: g or simulation not initialized')
    return
  }
  
  try {
  // 准备数据
    const nodes = graphData.value.nodes.slice(0, nodeLimit.value)
    const nodeIds = new Set(nodes.map(node => node.id))
    
    // 筛选链接
    const links = graphData.value.links.filter(link => {
      return nodeIds.has(link.source) && nodeIds.has(link.target)
    })
    
    // 处理链接引用
    const processedLinks = links.map(link => {
      const processedLink = {...link}
      
      if (typeof processedLink.source === 'string') {
        const sourceNode = nodes.find(n => n.id === processedLink.source)
        if (sourceNode) processedLink.source = sourceNode
      }
      
      if (typeof processedLink.target === 'string') {
        const targetNode = nodes.find(n => n.id === processedLink.target)
        if (targetNode) processedLink.target = targetNode
      }
      
      return processedLink
    }).filter(link => 
      typeof link.source !== 'string' && 
      typeof link.target !== 'string'
    )
    
    console.log(`Processing ${nodes.length} nodes and ${processedLinks.length} links`)
    
    // 清除现有元素
    g.selectAll('.link, .link-label-group, .node-group').remove()
    
    // 创建链接
    const link = g.selectAll('.link')
      .data(processedLinks)
      .enter()
      .append('line')
    .attr('class', 'link')
      .attr('stroke', d => getTrustScoreColor(d.trust_score || 0))
      .attr('stroke-width', 2)
      .attr('stroke-opacity', 0.8)
    .attr('marker-end', 'url(#arrowhead)')
    
    // 添加关系标签组 - 使用g元素包装标签和背景
    const linkLabelGroups = g.selectAll('.link-label-group')
      .data(processedLinks)
      .enter()
      .append('g')
      .attr('class', 'link-label-group')
      .style('pointer-events', 'none')
      .style('user-select', 'none');
      
    // 为每个关系组添加背景矩形
    const linkLabelBgs = linkLabelGroups
      .append('rect')
      .attr('class', 'link-label-bg')
      .attr('fill', 'rgba(0,0,0,0.5)')
      .attr('rx', 3)
      .attr('ry', 3)
      .attr('width', 1) // 初始宽度，将在tick函数中更新
      .attr('height', 1); // 初始高度，将在tick函数中更新
      
    // 添加文本标签
    const linkLabels = linkLabelGroups
      .append('text')
      .attr('class', 'link-label')
    .text(d => {
        // 如果关系名称太长，则截断
        const relationName = d.type || '';
        return relationName.length > 12 ? relationName.substring(0, 10) + '...' : relationName;
      })
      .attr('font-size', '10px')
      .attr('text-anchor', 'middle')
      .attr('fill', 'white')
      .attr('font-weight', 'bold')
      .attr('dy', '.35em') // 垂直居中
      .style('text-shadow', '0 0 3px rgba(0,0,0,0.8)')
      .each(function(d) {
        // 对长关系名称添加完整的title作为tooltip
        if (d.type && d.type.length > 12) {
          d3.select(this).append('title').text(d.type);
        }
      });
    
    // 创建节点组
    const nodeGroup = g.selectAll('.node-group')
    .data(nodes)
      .enter()
      .append('g')
      .attr('class', 'node-group')
      .call(d3.drag()
        .on('start', dragstarted)
        .on('drag', dragged)
        .on('end', dragended))
      .on('click', (event, d) => {
        event.stopPropagation()
        selectedNode.value = d
      })
      .on('dblclick', (event, d) => {
        // 添加双击功能，用于固定/解除固定节点
        event.stopPropagation()
        if (d.fx !== null && d.fy !== null) {
          // 节点已固定，解除固定
          d.fx = null
          d.fy = null
          // 更新视觉样式 - 恢复原始边框
          d3.select(event.currentTarget).select('circle')
            .transition()
            .duration(300)
            .attr('stroke', '#fff')
            .attr('stroke-width', 1.5)
        } else {
          // 节点未固定，固定在当前位置
          d.fx = d.x
          d.fy = d.y
          // 更新视觉样式 - 添加黄色边框指示固定状态
          d3.select(event.currentTarget).select('circle')
            .transition()
            .duration(300)
            .attr('stroke', '#FFFF00')
            .attr('stroke-width', 2.5)
        }
      })
    
    // 添加节点圆形
    nodeGroup.append('circle')
    .attr('class', 'node')
    .attr('r', 20)
      .attr('fill', d => getNodeColor(d.type))
      .attr('stroke', '#fff')
      .attr('stroke-width', 1.5)
      .attr('stroke-opacity', 0.9)
      .on('mouseover', function(event, d) {
        d3.select(this)
          .transition()
          .duration(200)
          .attr('r', 25)
          .attr('stroke-width', 2.5)
      })
      .on('mouseout', function(event, d) {
        // 如果节点不是固定状态，恢复正常样式
        const isFixed = d.fx !== null && d.fy !== null
        d3.select(this)
          .transition()
          .duration(200)
          .attr('r', 20)
          .attr('stroke-width', isFixed ? 2.5 : 1.5)
          .attr('stroke', isFixed ? '#FFFF00' : '#fff')
      })
    
    // 添加节点文字
    nodeGroup.append('text')
      .attr('dy', '.35em')
      .attr('text-anchor', 'middle')
      .attr('fill', 'white')
      .attr('font-size', '10px')
      .attr('pointer-events', 'none')
      .text(d => {
        const text = d.name || d.id
        return text.length > 10 ? text.substring(0, 8) + '...' : text
      })
    
    // 更新模拟
    simulation.value
      .nodes(nodes)
      .on('tick', () => {
        // 更新连线位置
        link
          .attr('x1', d => d.source.x)
          .attr('y1', d => d.source.y)
          .attr('x2', d => d.target.x)
          .attr('y2', d => d.target.y)
        
        // 更新链接标签组位置
        linkLabelGroups.each(function(d) {
          // 计算连线中点
          const midX = (d.source.x + d.target.x) / 2;
          const midY = (d.source.y + d.target.y) / 2;
          
          // 获取连线角度以实现文本旋转
          const angle = Math.atan2(d.target.y - d.source.y, d.target.x - d.source.x) * 180 / Math.PI;
          
          // 将标签组移动到连线中点
          d3.select(this)
            .attr('transform', `translate(${midX}, ${midY})`);
          
          // 获取标签文本元素和背景元素
          const textElement = d3.select(this).select('text');
          const bgElement = d3.select(this).select('rect');
          
          // 获取文本边界框
          const bbox = textElement.node().getBBox();
          
          // 更新背景矩形尺寸和位置
          const padding = 3;
          bgElement
            .attr('x', bbox.x - padding)
            .attr('y', bbox.y - padding)
            .attr('width', bbox.width + (padding * 2))
            .attr('height', bbox.height + (padding * 2));
        });
        
        // 更新节点组位置
        nodeGroup.attr('transform', d => `translate(${d.x}, ${d.y})`)
      })
    
    simulation.value.force('link').links(processedLinks)
    
    // 增加排斥力
    simulation.value.force('charge', d3.forceManyBody().strength(-300))
    
    // 防止节点重叠
    simulation.value.force('collide', d3.forceCollide().radius(50))
    
    simulation.value.alpha(1).restart()
    
    console.log('Started simulation')
    
    // 添加点击空白区域关闭节点信息的功能
    svg.on('click', () => {
      selectedNode.value = null
    })
    
    // 自动居中视图
    resetGraph()
    
  } catch (error) {
    console.error('Error updating graph:', error)
    ElMessage.error('更新图谱时发生错误')
  }
}

// 拖拽开始
function dragstarted(event, d) {
  if (!event.active) simulation.value.alphaTarget(0.3).restart()
  
  // 保存原始位置 - 用于临时拖动
  if (d.fx === null && d.fy === null) {
    d.tempDrag = true // 标记为临时拖动
  }
  
  d.fx = d.x
  d.fy = d.y
  
  // 添加视觉反馈
  d3.select(event.sourceEvent.currentTarget).select('circle')
    .transition()
    .duration(200)
    .attr('stroke', '#FFFF00')
    .attr('stroke-width', 2.5)
}

// 拖拽中
function dragged(event, d) {
  d.fx = event.x
  d.fy = event.y
}

// 拖拽结束
function dragended(event, d) {
  if (!event.active) simulation.value.alphaTarget(0)
  
  // 如果是临时拖动（没有通过双击固定），则拖拽结束后释放节点
  if (d.tempDrag) {
    d.fx = null
    d.fy = null
    d.tempDrag = false
    
    // 恢复原始边框样式
    d3.select(event.sourceEvent.currentTarget).select('circle')
      .transition()
      .duration(200)
      .attr('stroke', '#fff')
      .attr('stroke-width', 1.5)
  }
}

// 重置图谱视图
const resetGraph = () => {
  if (!svg || !g) return
  
  svg.transition()
    .duration(750)
    .call(zoom.transform, d3.zoomIdentity
      .translate(width / 2, height / 2)
      .scale(0.8)
      .translate(-width / 2, -height / 2))
}

// 关闭节点信息面板
const closeNodeInfo = () => {
  selectedNode.value = null
}

// 强制重新渲染图谱
const forceRenderGraph = () => {
  console.log('Force rendering graph');
  if (!graphContainer.value) {
    console.error('图谱容器不存在，无法渲染');
    return;
  }
  
  if (!graphData.value.nodes.length) {
    console.error('没有图谱数据，无法渲染');
    return;
  }
  
  // 确保容器有合适的尺寸
  const container = graphContainer.value;
  if (!container.clientWidth || !container.clientHeight) {
    console.log('Container has no dimensions, setting default size');
    container.style.width = '100%';
    container.style.height = '600px';
  }
  
  console.log('容器尺寸:', container.clientWidth, container.clientHeight);
  
  // 延迟短暂时间重新渲染，确保DOM已更新
  setTimeout(() => {
    if (svg && g) {
      console.log('Re-rendering existing graph');
      updateGraph();
    } else {
      console.log('Creating new graph');
      initGraph();
    }
    
    // 标记为已渲染
    graphRendered.value = true;
  }, 300);
}

// 获取实体类型列表
const loadEntityTypes = async () => {
  try {
    console.log('正在加载实体类型...')
    const response = await axios.get('http://localhost:8000/entity-types')
    
    if (response.data && Array.isArray(response.data)) {
      entityTypes.value = response.data
      
      // 初始化过滤器
      entityTypes.value.forEach(type => {
        if (!entityTypeFilters.hasOwnProperty(type.type)) {
          entityTypeFilters[type.type] = true  // 默认选中所有类型
        }
      })
      
      console.log(`成功加载 ${entityTypes.value.length} 个实体类型`)
    } else {
      console.error('实体类型数据格式不正确')
    }
  } catch (err) {
    console.error('加载实体类型失败:', err)
    ElMessage.error('加载实体类型失败')
  }
}

// 应用筛选
const applyFilters = () => {
  console.log('应用筛选', entityTypeFilters)
  
  // 筛选节点
  updateGraphData()
}

// 重置筛选
const resetFilters = () => {
  // 重置所有筛选器为默认值
  entityTypes.value.forEach(type => {
    entityTypeFilters[type.type] = true
  })
  
  // 重新加载图数据
  loadGraphData()
}

// 更新图数据（应用筛选）
const updateGraphData = () => {
  if (!graphData.value.nodes || !graphData.value.links) {
    return
  }
  
  // 应用实体类型过滤
  const selectedTypes = Object.entries(entityTypeFilters)
    .filter(([_, selected]) => selected)
    .map(([type]) => type)
  
  // 如果没有选择任何类型，显示全部
  const filteredNodes = selectedTypes.length === 0 
    ? graphData.value.nodes 
    : graphData.value.nodes.filter(node => selectedTypes.includes(node.type))
  
  // 过滤链接，只保留连接两个可见节点的链接
  const visibleNodeIds = new Set(filteredNodes.map(node => node.id))
  const filteredLinks = graphData.value.links.filter(link => 
    visibleNodeIds.has(link.source) && visibleNodeIds.has(link.target)
  )
  
  // 更新图谱数据
  graphData.value = {
    nodes: filteredNodes.slice(0, nodeLimit.value),
    links: filteredLinks
  }
  
  // 重新渲染图谱
  forceRenderGraph()
}
</script>

<style scoped>
.trust-evaluation-container {
  padding-bottom: 20px;
  width: 100%;
  height: 100%;
}

.main-layout {
  display: flex;
  width: 100%;
  height: calc(100vh - 120px);
  overflow: hidden;
}

.sidebar-controls {
  width: 250px;
  background-color: #1e2124;
  color: #eee;
  padding: 15px;
  overflow-y: auto;
  flex-shrink: 0;
  box-shadow: 2px 0 10px rgba(0, 0, 0, 0.3);
}

.main-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
}

.sidebar-header {
  margin-bottom: 20px;
  padding-bottom: 10px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.sidebar-title {
  font-size: 20px;
  color: #fff;
  margin: 0;
  text-align: center;
}

.control-section {
  margin-bottom: 20px;
  padding-bottom: 15px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.section-title {
  font-size: 16px;
  font-weight: bold;
  margin-bottom: 10px;
  color: #fff;
}

.graph-area {
  flex: 1;
  position: relative;
  background: #21252b;
}

.graph-container {
  width: 100%;
  height: 100%;
  position: relative;
}

/* 可信度标识样式 */
.trust-legend {
  display: flex;
  flex-direction: column;
  background-color: rgba(33, 37, 43, 0.7);
  border-radius: 4px;
  padding: 8px;
  gap: 5px;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 10px;
}

.color-bar {
  width: 15px;
  height: 15px;
  border-radius: 2px;
}

/* 搜索框样式 */
.search-box {
  margin-bottom: 10px;
}

.search-input {
  margin-bottom: 10px;
}

.search-buttons {
  display: flex;
  gap: 10px;
  margin-bottom: 10px;
}

.search-btn {
  flex: 1;
  font-size: 12px;
}

/* 表单样式 */
.entity-form {
  margin-bottom: 15px;
}

.form-select {
  width: 100%;
}

.form-actions {
  display: flex;
  gap: 10px;
}

/* 实体类型选择器样式 */
.entity-types {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-height: 200px;
  overflow-y: auto;
  padding-right: 5px;
}

.no-types-message {
  color: #999;
  text-align: center;
  padding: 10px;
}

.filter-button {
  width: 100%;
  margin-bottom: 10px;
}

/* D3可视化样式 */
:deep(.graph-svg) {
  width: 100%;
  height: 100%;
  background-color: #21252b;
}

:deep(.node) {
  stroke: #fff;
  stroke-width: 1.5px;
  cursor: pointer;
}

:deep(.link) {
  stroke-opacity: 0.6;
}

:deep(.link-label) {
  font-family: Arial, sans-serif;
  font-weight: bold;
  pointer-events: none;
  user-select: none;
  text-shadow: 0 0 3px rgba(0, 0, 0, 0.8);
}

:deep(.link-label-bg) {
  opacity: 0.7;
  rx: 3;
  ry: 3;
}

/* 加载和错误状态 */
.loading-overlay, .error-container, .graph-loading {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: rgba(0, 0, 0, 0.7);
  color: white;
  z-index: 10;
}

.spinner {
  width: 50px;
  height: 50px;
  border: 5px solid rgba(255, 255, 255, 0.2);
  border-top-color: #3498db;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-bottom: 15px;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* 节点信息面板 */
.node-info-panel {
  position: absolute;
  top: 20px;
  right: 20px;
  width: 300px;
  background-color: rgba(34, 38, 46, 0.9);
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.3);
  color: #eee;
  z-index: 100;
}

.node-info-header {
  padding: 10px 15px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid #383c40;
}

.node-info-header h3 {
  margin: 0;
  font-size: 16px;
}

.node-info-content {
  padding: 15px;
  max-height: 300px;
  overflow-y: auto;
}

.info-item {
  margin-bottom: 8px;
  display: flex;
}

.item-label {
  width: 80px;
  font-weight: bold;
  color: #bbb;
}

.item-value {
  flex: 1;
}

/* 评估结果区域 */
.evaluation-results {
  background-color: rgba(34, 38, 46, 0.9);
  margin: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.3);
  color: #eee;
  max-height: 300px;
  position: absolute;
  bottom: 20px;
  right: 20px;
  width: 400px;
  z-index: 100;
}

.result-header {
  padding: 15px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid #383c40;
}

.result-header h3 {
  margin: 0;
  font-size: 18px;
}

.result-content {
  padding: 15px;
  overflow-y: auto;
  max-height: 220px;
}

.factors-section {
  margin-top: 15px;
}

.factors-section h4 {
  margin-top: 0;
  margin-bottom: 15px;
}

.factors-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 15px;
}

.factor-card {
  background-color: rgba(0, 0, 0, 0.2);
  padding: 15px;
  border-radius: 8px;
  text-align: center;
}

.factor-title {
  margin-bottom: 10px;
  font-weight: bold;
  font-size: 14px;
}

.factor-score {
  font-size: 18px;
  font-weight: bold;
  margin-top: 5px;
}

.trust-score-badge {
  background-color: #333;
  padding: 5px 10px;
  border-radius: 15px;
  font-weight: bold;
}

.high-trust {
  background-color: #67C23A;
}

.medium-trust {
  background-color: #E6A23C;
}

.low-trust {
  background-color: #F56C6C;
}
</style> 